package com.compmov.webservice;

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.Map;
import java.util.Properties;

import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.params.ClientPNames;
import org.apache.http.client.params.CookiePolicy;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;
import org.json.JSONException;
import org.json.JSONObject;

import android.os.Environment;
import android.util.Log;

import com.compmov.datamodel.Persona;
import com.compmov.libraries.Utils;
import com.google.gson.Gson;

public class WebServiceClient {
	private DefaultHttpClient httpClient;
	private HttpContext localContext;
    private String ret;
 
    private HttpResponse response = null;
    private HttpPost httpPost = null;
    private HttpGet httpGet = null;
    private String webServiceUrl;
    private static String serverURL;

    private static final String TAG="WEBSERVICE_TEST";
    
    /**
     * Constructor del cliente del web service, debe recibir el nombre del servicio a consumir
     * @param serviceName Nombre del webservice
     */
    public WebServiceClient(String serviceName){
        HttpParams myParams = new BasicHttpParams();
 
        HttpConnectionParams.setConnectionTimeout(myParams, 10000);
        HttpConnectionParams.setSoTimeout(myParams, 10000);
        httpClient = new DefaultHttpClient(myParams);
        localContext = new BasicHttpContext();
        //serverURL = "http://192.168.50.151:8080/AdviseMe_Server";
        serverURL = loadServerURLFromFile();
        webServiceUrl = serverURL+serviceName;
    }
    
    public static String getServerURL() {
		return serverURL;
	}

    public static void setServerURL(String serverURL) {
		WebServiceClient.serverURL = serverURL;
	}

    
    public String getWebServiceUrl() {
		return webServiceUrl;
	}

	public void setWebServiceUrl(String webServiceUrl) {
		this.webServiceUrl = webServiceUrl;
	}

	public String loadServerURLFromFile(){
    	String url ="";
    	// Se intenta leer el archivo de propiedades
    	Properties appProperties = Utils.loadPropertyFile(Environment.getExternalStorageDirectory()
				.getAbsolutePath());

		// Si el archivo de propiedades esta vacio, quiere decir que es la
		// primera vez que se
		// corre la aplicacion, por lo que es necesario almacenar la direccion del servidor por
    	// default

		if (appProperties.isEmpty()) {
			Log.i(TAG, "Generando Archivo de Propiedades");
			appProperties.setProperty("ServerURL", Utils.DEFAULT_SERVER_URL);
			Utils.savePropertyFile(Environment.getExternalStorageDirectory().getAbsolutePath(),
					appProperties);
			url = Utils.DEFAULT_SERVER_URL;
		} else {
			// Se obtiene la SIM almacenada en el archivo
			url = appProperties.getProperty("ServerURL");
		}
		return url;

    }

	/**
     * Metodo para invocar al webservice mediante HttpPost
     * @param methodName Nombre del metodo en el webservice que se invocara
     * @param params Parametros que recibira el webService
     * @return Retorna la cadena retornada por el servidor
     */
    public String webPut(String methodName, Map<String, String> params) {
 
        JSONObject jsonObject = new JSONObject();
 
        //Llenado de parametros en el objeto de JSON
        for (Map.Entry<String, String> param : params.entrySet()){
            try {
                jsonObject.put(param.getKey(), param.getValue());
            }
            catch (JSONException e) {
                Log.e(TAG, "JSONException : "+e);
            }
        }
        //Se invoca al webservice, utilizando JSON
        return webPut(methodName,  jsonObject.toString(), "application/json");
    }
 
    /**
     * Invocacion del webService mediante Post
     * @param methodName Nombre del metodo en el webService
     * @param data Cadena en formato JSON con los parametros del WebService
     * @param contentType MIME type en el que viajaran los datos del webService
     */
    private String webPut(String methodName, String data, String contentType) {
        ret = null;
 
        httpClient.getParams().setParameter(ClientPNames.COOKIE_POLICY, CookiePolicy.RFC_2109);
 
        httpPost = new HttpPost(webServiceUrl + methodName);
        response = null;
 
        StringEntity tmp = null;       
 
        //httpPost.setHeader("User-Agent", "SET YOUR USER AGENT STRING HERE");
        httpPost.setHeader("Accept","application/xml,application/json");
 
        if (contentType != null) {
            httpPost.setHeader("Content-Type", contentType);
        } else {
            httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded");
        }
 
        try {
            tmp = new StringEntity(data,"UTF-8");
        } catch (UnsupportedEncodingException e) {
            Log.e(TAG, "HttpUtils : UnsupportedEncodingException : "+e);
        }
 
        httpPost.setEntity(tmp);
 
        Log.d(TAG, webServiceUrl + "?" + data);
 
        try {
            response = httpClient.execute(httpPost,localContext);
 
            if (response != null) {
                ret = EntityUtils.toString(response.getEntity());
            }
        } catch (Exception e) {
            Log.e(TAG, "HttpUtils: " + e);
        }
 
        return ret;
    }
 
    //Use this method to do a HttpGet/WebGet on the web service
    public String webGet(String methodName, Map<String, String> params) {
        String getUrl = webServiceUrl + methodName;
 
        int i = 0;
        //Parseo de parametros para invocacion por GET
        for (Map.Entry<String, String> param : params.entrySet())
        {
            if(i == 0){
                getUrl += "?";
            }
            else{
                getUrl += "&";
            }
 
            try {
                getUrl += param.getKey() + "=" + URLEncoder.encode(param.getValue(),"UTF-8");
            } catch (UnsupportedEncodingException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
 
            i++;
        }
 
        httpGet = new HttpGet(getUrl);
        httpGet.setHeader("Accept", "application/json");
        httpGet.setHeader("Content-Type", "application/json");
        Log.d(TAG,getUrl);
 
        try {
            response = httpClient.execute(httpGet);
        } catch (Exception e) {
            Log.e(TAG, "ERROR en EXECUTE: "+e.getMessage());
        }
 
        // Parseo del response
        try {
            ret = EntityUtils.toString(response.getEntity());
            Log.d(TAG,"RES = "+ret);
        } catch (IOException e) {
            Log.e(TAG, "Error en Resultado: "+e.getMessage());
        }
 
        return ret;
    }
 
    public static JSONObject Object(Object o){
        try {
            return new JSONObject(new Gson().toJson(o));
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return null;
    }
 
    public InputStream getHttpStream(String urlString) throws IOException {
        InputStream in = null;
        int response = -1;
 
        URL url = new URL(urlString);
        URLConnection conn = url.openConnection();
 
        if (!(conn instanceof HttpURLConnection))
            throw new IOException("Not an HTTP connection");
 
        try{
            HttpURLConnection httpConn = (HttpURLConnection) conn;
            httpConn.setAllowUserInteraction(false);
            httpConn.setInstanceFollowRedirects(true);
            httpConn.setRequestMethod("GET");
            httpConn.connect();
 
            response = httpConn.getResponseCode();                
 
            if (response == HttpURLConnection.HTTP_OK) {
                in = httpConn.getInputStream();
            }
        } catch (Exception e) {
            throw new IOException("Error connecting");
        } // end try-catch
 
        return in;
    }
 
    public void clearCookies() {
        httpClient.getCookieStore().clear();
    }
 
    public void abort() {
        try {
            if (httpClient != null) {
                Log.i(TAG,"ABORT");
                httpPost.abort();
            }
        } catch (Exception e) {
        	Log.e(TAG, e.getMessage(),e);
        }
    }
}
